from typing import Optional, Dict, Any
from datetime import date, datetime, timedelta
from tortoise.exceptions import DoesNotExist
from src.models.user import User
from src.models.checkin_record import CheckinRecord
from src.utils.logger import app_logger as logger
from src.config.settings import get_settings


class CheckinService:
    """打卡服务"""
    
    @staticmethod
    async def perform_checkin(user_id: int) -> Dict[str, Any]:
        """执行打卡操作"""
        try:
            # 获取用户信息
            user = await User.get(id=user_id)
            
            # 检查今日是否已打卡（检查用户状态和打卡记录）
            today = date.today()
            existing_record = await CheckinRecord.filter(user_id=user_id, checkin_date=today).first()
            
            # 先进行状态同步，确保数据一致性
            if existing_record and not user.is_checkin:
                # 如果有打卡记录但用户状态未更新，同步用户状态
                user.is_checkin = True
                await user.save()
                logger.info(f"用户 {user_id} 状态已同步为已打卡")
                # 状态同步场景，返回已打卡消息（避免误导用户以为获得了新积分）
                return {
                    "success": True,
                    "message": "今日已打卡",
                    "data": {
                        "is_checkin": True,
                        "total_checkin_days": user.total_checkin_days,
                        "continuous_checkin_days": user.continuous_checkin_days,
                        "points_awarded": existing_record.points_awarded if existing_record else 0,
                        "current_points": user.points,
                        "checkin_date": today.isoformat()
                    }
                }
            
            # 检查是否已打卡
            if user.is_checkin or existing_record:
                return {
                    "success": True,
                    "message": "今日已打卡",
                    "data": {
                        "is_checkin": True,
                        "total_checkin_days": user.total_checkin_days,
                        "continuous_checkin_days": user.continuous_checkin_days,
                        "points_awarded": existing_record.points_awarded if existing_record else 0,
                        "current_points": user.points,
                        "checkin_date": today.isoformat()
                    }
                }
            
            yesterday = today - timedelta(days=1)
            
            # 计算连续打卡天数
            if user.last_checkin_date == yesterday:
                # 连续打卡
                continuous_days = user.continuous_checkin_days + 1
            else:
                # 中断了，重新开始
                continuous_days = 1
            
            # 计算奖励积分（基础积分 + 连续奖励）
            settings = get_settings()
            base_points = getattr(settings, 'CHECKIN_BASE_POINTS', 10)  # 基础积分
            bonus_points = min(continuous_days - 1, 10) * 2  # 连续奖励，最多20分
            total_points = base_points + bonus_points
            
            # 更新用户信息
            user.is_checkin = True
            user.total_checkin_days += 1
            user.continuous_checkin_days = continuous_days
            user.last_checkin_date = today
            user.points += total_points
            await user.save()
            
            # 创建打卡记录
            checkin_record = await CheckinRecord.create(
                user_id=user_id,
                checkin_date=today,
                points_awarded=total_points,
                continuous_days=continuous_days
            )
            
            logger.info(f"用户 {user_id} 打卡成功，获得 {total_points} 积分，连续打卡 {continuous_days} 天")
            
            return {
                "success": True,
                "message": f"打卡成功！获得 {total_points} 积分",
                "data": {
                    "is_checkin": True,
                    "total_checkin_days": user.total_checkin_days,
                    "continuous_checkin_days": continuous_days,
                    "points_awarded": total_points,
                    "current_points": user.points,
                    "checkin_date": today.isoformat()
                }
            }
            
        except DoesNotExist:
            logger.error(f"用户 {user_id} 不存在")
            return {
                "success": False,
                "message": "用户不存在",
                "data": None
            }
        except Exception as e:
            logger.error(f"打卡失败: {str(e)}")
            return {
                "success": False,
                "message": f"打卡失败: {str(e)}",
                "data": None
            }
    
    @staticmethod
    async def get_checkin_status(user_id: int) -> Dict[str, Any]:
        """获取用户打卡状态"""
        try:
            user = await User.get(id=user_id)
            
            return {
                "success": True,
                "data": {
                    "is_checkin": user.is_checkin,
                    "total_checkin_days": user.total_checkin_days,
                    "continuous_checkin_days": user.continuous_checkin_days,
                    "last_checkin_date": user.last_checkin_date.isoformat() if user.last_checkin_date else None,
                    "current_points": user.points
                }
            }
            
        except DoesNotExist:
            return {
                "success": False,
                "message": "用户不存在",
                "data": None
            }
        except Exception as e:
            logger.error(f"获取打卡状态失败: {str(e)}")
            return {
                "success": False,
                "message": f"获取打卡状态失败: {str(e)}",
                "data": None
            }
    
    @staticmethod
    async def get_checkin_history(user_id: int, page: int = 1, limit: int = 10) -> Dict[str, Any]:
        """获取用户打卡历史"""
        try:
            # 计算偏移量
            offset = (page - 1) * limit
            
            # 查询打卡记录
            records = await CheckinRecord.filter(
                user_id=user_id
            ).offset(offset).limit(limit).order_by("-checkin_date")
            
            # 获取总数
            total = await CheckinRecord.filter(user_id=user_id).count()
            
            # 格式化数据
            history_data = []
            for record in records:
                history_data.append({
                    "id": record.id,
                    "checkin_date": record.checkin_date.isoformat(),
                    "points_awarded": record.points_awarded,
                    "continuous_days": record.continuous_days,
                    "created_at": record.created_at.isoformat()
                })
            
            return {
                "success": True,
                "data": {
                    "records": history_data,
                    "total": total,
                    "page": page,
                    "limit": limit,
                    "has_more": offset + limit < total
                }
            }
            
        except Exception as e:
            logger.error(f"获取打卡历史失败: {str(e)}")
            return {
                "success": False,
                "message": f"获取打卡历史失败: {str(e)}",
                "data": None
            }
    
    @staticmethod
    async def get_checkin_summary(user_id: int, year: int, month: int) -> Dict[str, Any]:
        """获取用户指定年月的打卡汇总数据"""
        try:
            # 构建查询的开始和结束日期
            start_date = date(year, month, 1)
            if month == 12:
                end_date = date(year + 1, 1, 1) - timedelta(days=1)
            else:
                end_date = date(year, month + 1, 1) - timedelta(days=1)
            
            # 查询该月的所有打卡记录
            records = await CheckinRecord.filter(
                user_id=user_id,
                checkin_date__gte=start_date,
                checkin_date__lte=end_date
            ).order_by('checkin_date')
            
            # 计算汇总数据
            total_checkin_count = len(records)
            max_continuous_days = max([record.continuous_days for record in records]) if records else 0
            
            # 构建返回数据
            checkin_records = [
                record.checkin_date.isoformat()
                for record in records
            ]
            
            return {
                "success": True,
                "message": "获取打卡汇总成功",
                "data": {
                    "year": year,
                    "month": month,
                    "total_checkin_count": total_checkin_count,
                    "max_continuous_days": max_continuous_days,
                    "checkin_records": checkin_records
                }
            }
            
        except Exception as e:
            logger.error(f"获取打卡汇总失败: {str(e)}")
            return {
                "success": False,
                "message": f"获取打卡汇总失败: {str(e)}",
                "data": None
            }
    
    @staticmethod
    async def reset_daily_checkin():
        """重置所有用户的每日打卡状态（定时任务调用）"""
        try:
            # 重置所有用户的is_checkin字段为False
            await User.all().update(is_checkin=False)
            
            # 检查连续打卡是否中断
            yesterday = date.today() - timedelta(days=1)
            users = await User.filter(last_checkin_date__lt=yesterday, continuous_checkin_days__gt=0)
            
            # 重置中断用户的连续打卡天数
            for user in users:
                user.continuous_checkin_days = 0
                await user.save()
            
            logger.info(f"每日打卡状态重置完成，共重置 {len(users)} 个用户的连续打卡天数")
            
        except Exception as e:
            logger.error(f"重置每日打卡状态失败: {str(e)}")